/*
 * MODULE  NAME  :
 * PROGRAM NAME  : net.h
 * AUTHOR        : hotmocha(hotmocha@126.com)
 * CREATE  DATE  : 2015-10-21 08:49:53
 * PROGRAM DESC  :
 *
 * HISTORY       :
 *
 */
#ifndef _H_TKEVENT_H_
#define _H_TKEVENT_H_

#include <sys/epoll.h>
#include "constants.h"
#include <arpa/inet.h>

#ifndef EPOLLRDHUP
	#define EPOLLRDHUP 0
#endif

#define EVENT_LOCAL_ERROR	1
#define EVENT_REMOTE_CLOSE	2
#define EVENT_READ		4
#define EVENT_WRITE		8

#define EPOLL_EVENT_R	EPOLLIN
#define EPOLL_EVENT_W	EPOLLOUT
#define EPOLL_EVENT_RW	(EPOLLOUT | EPOLLIN)

struct epoll_env;
struct tk_connect;
struct custom_socket;
typedef int (*event_handler)(struct epoll_env *env, struct custom_socket *s, void *pv, int event_type);

struct net_addr {
	int port;
	char ipv4[IPV4LEN];
        struct sockaddr_in sockaddr;
};

struct custom_socket {
        int sockfd;
        struct net_addr addr;
	void* event;		/* custom_event */
	event_handler handler;
	int type;		/* listen or default */
	
	void *conn_ptr;		/* point to tk_connect */

        int merrno;		/* tk custom errno */
        int eerrno;		/* system errno */
        int finished:1;
        int failed:1;		/* send error information to client and status to finished(no matter send success or failed) */

	void *pv;		/* custom data or point to a function */
};

typedef int (*after_accept_entry)(struct epoll_env *env, struct custom_socket *s, void *pv);
typedef int (*after_connect_entry)(struct epoll_env *env, struct custom_socket *s, void *pv);
struct epoll_env {
	int epollfd;
	struct epoll_event *epoll_wait_events;	

	after_accept_entry after_accept;
	after_connect_entry after_connect;
};

void set_custom_socket_pv(struct custom_socket *s, void *pv);
void* get_custom_socket_pv(struct custom_socket *s);

void set_epoll_after_accept(struct epoll_env *env, after_accept_entry after_accept);
void set_epoll_after_connect(struct epoll_env *env, after_connect_entry after_connect);

int epoll_process_events(struct epoll_env* env, int timeout);

int epoll_del_event(struct epoll_env *env, void *event, int event_type);
int epoll_add_listen_event(struct epoll_env *env, void *event);
int epoll_del_listen_event(struct epoll_env *env, void *event);
int epoll_add_read_event(struct epoll_env *env, void *event);
int epoll_add_write_event(struct epoll_env *env, void *event);
int epoll_del_read_event(struct epoll_env *env, void *event);
int epoll_del_write_event(struct epoll_env *env, void *event);
int epoll_set_event(struct epoll_env *env, void *event, int event_type);
int epoll_del_fd(struct epoll_env *env, void *event);


int is_accept(void *pv);
int is_writable(void *pv);
int is_readable(void *pv);
int is_active(void *pv) ;
int is_active_read(void *pv);
int is_active_write(void *pv);
int is_timeout(void *pv);
int is_in_timer_set(void *pv);
int is_force_delay_read(void *pv);
int is_shutdown(void *pv);
int is_error(void *pv);
int is_force_delay_read(void *pv);

void set_accept(void *pv,int flag);
void set_writable(void *pv,int flag);
void set_readable(void *pv,int flag);
void set_active(void *pv,int flag) ;
void set_active_read(void *pv,int flag);
void set_active_write(void *pv,int flag);
void set_timeout(void *pv,int flag);
void set_in_timer_set(void *pv,int flag);
void set_force_delay_read(void *pv,int flag);
void set_shutdown(void *pv,int flag);
void set_error(void *pv,int flag);
void set_force_delay_read(void *pv,int flag);

void set_event_data(void *pv, void *data);
void* get_event_data(void *pv);

struct custom_socket* get_custom_socket();
struct custom_socket* get_custom_listen_socket();
int init_custom_listen_socket(struct custom_socket *s, char *ip, int port);
void destory_custom_socket(struct epoll_env *env, struct custom_socket *s);

struct epoll_env* create_epoll_env(after_accept_entry after_accept, after_connect_entry after_connect);
int destory_epoll_env(struct epoll_env *env);
void set_event_type(void *pv, int type);

int tk_sendn(int fd, char *buf, int *buf_len);
int tk_recvn(int fd, char *buf, int *buf_len);
int tk_send(int fd, char *buf, int *buf_len);
int tk_recv(int fd, char *buf, int *buf_len);

#endif
